﻿/* ----------------------------------------------------------------------------
 * Copyright (c) Philip Stears 
 *
 * This source code is subject to terms and conditions of the Microsoft Public 
 * License (Ms-PL).
 * 
 * By using this source code in any fashion, you are agreeing to be bound 
 * by the terms of the Microsoft Public License.
 * 
 * To request a copy of the Microsoft Public License, send a request by email
 * to license@connectbasic.net.
 *
 * This notice must not be removed from this software.
 * ---------------------------------------------------------------------------- */

namespace ConnectBasic
{
    using System;
    using ConnectBasic.Execution;
    using Microsoft.Scripting.Hosting;

    /// <summary>
    /// Provides helpers methods for working with ConnectBasic.
    /// </summary>
    public static class BasicHelpers
    {   

        /// <summary>
        /// Creates a new script runtime which has been loaded with support for ConnectBasic.
        /// </summary>
        /// <param name="debugMode">Controls whether debug mode is enabled.</param>
        /// <param name="hostType">The type of a class which inherits from <see cref="ScriptHost" /> which is hosting the script.</param>
        /// <param name="hostArguments">The arguments provided to the script host constructor.</param>
        /// <returns></returns>
        public static ScriptRuntime CreateRuntime(bool debugMode, Type hostType, params object[] hostArguments)
        {
            return new ScriptRuntime(
                new ScriptRuntimeSetup()
                {
                    HostType = hostType ?? typeof(ScriptHost),
                    HostArguments = hostArguments,
                    DebugMode = false,
                    PrivateBinding = true,
                    LanguageSetups = { BasicLanguageContext.CreateLanguageSetup() },
                    Options = { {"EmitExpressionDebugger", true} }
                });
        }

        /// <summary>
        /// Creates a new script runtime which has been loaded with support for ConnectBasic.
        /// </summary>
        /// <param name="debugMode">Controls whether debug mode is enabled.</param>
        /// <returns></returns>
        public static ScriptRuntime CreateRuntime(bool debugMode)
        {
            return CreateRuntime(debugMode, null);
        }     

        /// <summary>
        /// Creates a script runtime loaded with support for ConnectBasic,
        /// and uses it to create and return a Script Engine.
        /// </summary>
        /// <param name="debugMode">Controls whether debug mode is enabled.</param>
        /// <param name="hostType">The type of a class which inherits from <see cref="ScriptHost" /> which is hosting the script.</param>        
        /// <param name="hostArguments">The arguments provided to the script host constructor.</param>
        /// <returns></returns>
        public static ScriptEngine CreateEngine(bool debugMode, Type hostType, params object[] hostArguments)
        {
            return CreateRuntime(debugMode, hostType, hostArguments).GetEngine("ConnectBasic");
        }

        /// <summary>
        /// Creates a script runtime loaded with support for ConnectBasic,
        /// and uses it to create and return a Script Engine.
        /// </summary>
        /// <param name="debugMode">Controls whether debug mode is enabled.</param>
        /// <returns></returns>
        public static ScriptEngine CreateEngine(bool debugMode)
        {
            return CreateEngine(debugMode, null);
        }

        /// <summary>
        /// Compiles and returns the standard module in the given source code file.
        /// </summary>
        /// <param name="debugMode">Controls whether debug mode is enabled.</param>
        /// <param name="path">The path to the module to compile.</param>
        /// <param name="hostType">The type of a class which inherits from <see cref="ScriptHost" /> which is hosting the script.</param>                
        /// <param name="hostArguments">The arguments provided to the script host constructor.</param>
        /// <returns>The compiled module</returns>
        public static BasicModule CompileStandardModule(bool debugMode, string path, Type hostType, params object[] hostArguments)
        {
            var engine = CreateEngine(debugMode, hostType, hostArguments);
            var source = engine.CreateScriptSourceFromFile(path);
            var code = source.Compile();

            return (BasicModule)code.Execute();
        }

        /// <summary>
        /// Compiles and returns the standard module in the given source code file.
        /// </summary>
        /// <param name="debugMode">Controls whether debug mode is enabled.</param>
        /// <param name="path">The path to the module to compile.</param>
        /// <returns>The compiled module</returns>
        public static BasicModule CompileStandardModule(bool debugMode, string path)
        {
            return CompileStandardModule(path, CreateRuntime(debugMode));
        }

        /// <summary>
        /// Compiles and returns the standard module in the given source code file.
        /// </summary>
        /// <param name="runtime">The script runtime.</param>
        /// <param name="path">The path to the module to compile.</param>
        /// <returns>The compiled module</returns>
        public static BasicModule CompileStandardModule(string path, ScriptRuntime runtime)
        {
            var engine = runtime.GetEngine("ConnectBasic");
            var source = engine.CreateScriptSourceFromFile(path);
            var code = source.Compile();

            return (BasicModule)code.Execute();
        }
    }
}
